package zpe.jsf.view.bean;

import static zpe.genericcrud.jsf.view.bean.FacesUtils.addErrorMessage;

import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.faces.model.SelectItem;

import zpe.controledeacesso.model.bean.Estado;
import zpe.controledeacesso.model.bean.Localidade;
import zpe.controledeacesso.model.bean.NivelAcesso;
import zpe.controledeacesso.model.bean.Usuario;
import zpe.controledeacesso.security.Acesso;
import zpe.controledeacesso.util.UsuarioUtil;
import zpe.genericcrud.exception.ApplicationException;
import zpe.genericcrud.jsf.view.bean.AbstractCrudBean;
import zpe.genericcrud.jsf.view.bean.FacesUtils;
import zpe.model.Cliente;
import zpe.model.ClienteEmail;
import zpe.model.ClienteUsuario;
import zpe.service.ClienteService;

@ManagedBean
@ViewScoped
public class ClienteBean extends AbstractCrudBean<Cliente, ClienteService> {
	
	private ClienteEmail email = new ClienteEmail();
	private DataModel<ClienteEmail> listEmail = new ListDataModel<ClienteEmail>();
	private Estado uf = new Estado();
	private List<SelectItem> niveis = new ArrayList<SelectItem>();
	private DataModel<Usuario> usuariosPesquisa = new ListDataModel<Usuario>( new ArrayList<Usuario>(0) );
	private DataModel<ClienteUsuario> usuariosAdicionados = new ListDataModel<ClienteUsuario>( new ArrayList<ClienteUsuario>(0) );
	private List<Usuario> listUsuarios = new ArrayList<Usuario>();
	private String pesquisa;
	
	@ManagedProperty("#{clienteService}")
	protected ClienteService serviceCliente;

	public void resetaCampos(){
		usuariosPesquisa = new ListDataModel<Usuario>( new ArrayList<Usuario>(0) );
		usuariosAdicionados = new ListDataModel<ClienteUsuario>( new ArrayList<ClienteUsuario>(0) );
		listUsuarios = new ArrayList<Usuario>();
		getEntity().setUsuarios(new ArrayList<ClienteUsuario>());
		pesquisa = "";
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public void save(ActionEvent event) {
		try{
			getEntity().setEmails((List<ClienteEmail>)listEmail.getWrappedData());
			super.save(event);
			getEntity().getEmails().clear();
			resetaCampos();
		} catch ( ApplicationException e ) {
			addErrorMessage( e.getMessage() );
		} catch ( Exception e ) {
			addErrorMessage( getMessage( "ERROR_INSERT" ) );
		}
	}
	
	@SuppressWarnings("unchecked")
	@Override
	public void update(ActionEvent event) {
		try {
			getEntity().setEmails((List<ClienteEmail>)listEmail.getWrappedData());
			if(getEntity().getEmails()!=null){
				for (int i = 0; i < getEntity().getEmails().size(); i++){
					getEntity().getEmails().get(i).setCliente(getEntity());
				}
			}
			
			ClienteUsuario c1 = new ClienteUsuario();
			c1.setCliente(getEntity());
			getEntity().setUsuarios(serviceCliente.getServiceClienteUsuario().findByFilter(ClienteUsuario.class, c1.notEmptyFields()));
			serviceCliente.getServiceClienteUsuario().removeAll(getEntity().getUsuarios());
			getEntity().setUsuarios(new ArrayList<ClienteUsuario>());

			if(usuariosAdicionados!=null){
				getEntity().setUsuarios((List<ClienteUsuario>) usuariosAdicionados.getWrappedData());
				for (int i = 0; i < getEntity().getUsuarios().size(); i++){
					getEntity().getUsuarios().get(i).setId(null);
					getEntity().getUsuarios().get(i).setCliente(getEntity());
				}
			}
			
			super.update(event);
			resetaCampos();
		} catch ( ApplicationException e ) {
			addErrorMessage( e.getMessage() );
		} catch ( Exception e ) {
			addErrorMessage( getMessage( "ERROR_INSERT" ) );
		}
	}
	
	public void findCliente(ActionEvent event){
		Usuario u = new Usuario();
		u.setDescricao(pesquisa);
		listUsuarios.clear();
		listUsuarios = serviceCliente.getServiceUsuario().findByFilter(Usuario.class, u.notEmptyFields(),"descricao");
		getUsuariosPesquisa().setWrappedData(listUsuarios);
	}
	
	public void adicionaCliente(ActionEvent event){
		try{
			for (ClienteUsuario c : getEntity().getUsuarios()) {
				if(c.getUsuario().getId().intValue() == getUsuariosPesquisa().getRowData().getId().intValue())
					throw new ApplicationException("Este usuário já possui permissão para este cliente!");
			}
			ClienteUsuario cu = new ClienteUsuario();
			cu.setUsuario(getUsuariosPesquisa().getRowData());
			getEntity().getUsuarios().add(cu);
			getUsuariosAdicionados().setWrappedData(getEntity().getUsuarios());
			listUsuarios.remove(getUsuariosPesquisa().getRowIndex());
			getUsuariosPesquisa().setWrappedData(listUsuarios);
		} catch (ApplicationException e){
			FacesUtils.addErrorMessage(e.getMessage());
		}
	}
	
	public void removeCliente(ActionEvent event){
		listUsuarios.add(getUsuariosAdicionados().getRowData().getUsuario());
		getUsuariosPesquisa().setWrappedData(listUsuarios);
		getEntity().getUsuarios().remove(getUsuariosAdicionados().getRowIndex());
		getUsuariosAdicionados().setWrappedData(getEntity().getUsuarios());
	}
	
	@SuppressWarnings("unchecked")
	public void adicionaEmail(ActionEvent event){
		List<ClienteEmail> l = (List<ClienteEmail>)getListEmail().getWrappedData();
		if(l!=null){
			l.add(email);
		} else {
			l = new ArrayList<ClienteEmail>();
			l.add(email);
		}
		listEmail.setWrappedData(l);
		email = new ClienteEmail(getEntity());
	}
	
	@SuppressWarnings("unchecked")
	public void removeEmail(ActionEvent event){
		List<ClienteEmail> l = (List<ClienteEmail>)getListEmail().getWrappedData();
		l.remove(getListEmail().getRowIndex());
		listEmail = new ListDataModel<ClienteEmail>();
		listEmail.setWrappedData(l);
	}

	public List<SelectItem> getEstados() {
		List<SelectItem> listUfs = new ArrayList<SelectItem>();
		List<Estado> l = serviceCliente.getServiceEstado().findAll(Estado.class);
		for (Estado uf : l)
			listUfs.add(new SelectItem(uf, uf.getDescricao()));
		return listUfs;
	}
	
	public List<SelectItem> getMunicipios() {
		List<SelectItem> listMunicipios = new ArrayList<SelectItem>();
		if(uf.getSigla()!=null){
			Localidade model = new Localidade();
			model.setEstado(getUf());
			List<Localidade> l = serviceCliente.getServiceLocalidade().findByFilter(Localidade.class, model.notEmptyFields());
			for (Localidade municipio : l)
				listMunicipios.add(new SelectItem(municipio, municipio.getDescricao()));
		}
		return listMunicipios;
	}
	
	@Override
	public void prepareInsert(ActionEvent event) {
		// TODO Auto-generated method stub
		resetaCampos();
		super.prepareInsert(event);
		preencheNiveis();
	}
	
	@Override
	public void prepareUpdate(ActionEvent event) {
		// TODO Auto-generated method stub
		resetaCampos();
		super.prepareUpdate(event);
		ClienteEmail c = new ClienteEmail();
		c.setCliente(getEntity());
		getEntity().setEmails(serviceCliente.getServiceClienteEmail().findByFilter(ClienteEmail.class, c.notEmptyFields()));
		setUf(getEntity().getMunicipio().getEstado());
		if(getEntity().getEmails()!=null && getEntity().getEmails().size() > 0)
			getListEmail().setWrappedData(getEntity().getEmails());
		
		ClienteUsuario c1 = new ClienteUsuario();
		c1.setCliente(getEntity());
		getEntity().setUsuarios(serviceCliente.getServiceClienteUsuario().findByFilter(ClienteUsuario.class, c1.notEmptyFields()));
		getUsuariosAdicionados().setWrappedData(getEntity().getUsuarios());
		preencheNiveis();
	}
	
	private void preencheNiveis(){
		int mod = Acesso.getModuloSistema();		
		Usuario usuario = UsuarioUtil.getUsuarioLogado();				
		NivelAcesso nivelSuperior = usuario.getMaiorNivel(mod);
		setNiveis(new ArrayList<SelectItem>());
		for( int i = 1; i < nivelSuperior.ordinal(); i++ ){
			SelectItem si = new SelectItem();
			si.setLabel( i + " - " + NivelAcesso.values()[i]);
			si.setValue( NivelAcesso.values()[i] );
			getNiveis().add( si );
		}
		if( nivelSuperior.equals( NivelAcesso.MASTER ) ){
			getNiveis().add( new SelectItem( nivelSuperior, nivelSuperior.ordinal() + " - " + nivelSuperior, null, true ) );
		}
	}
	
	public ClienteEmail getEmail() {
		return email;
	}

	public void setEmail(ClienteEmail email) {
		this.email = email;
	}

	public DataModel<ClienteEmail> getListEmail() {
		return listEmail;
	}

	public void setListEmail(DataModel<ClienteEmail> listEmail) {
		this.listEmail = listEmail;
	}
	
	public Estado getUf() {
		return uf;
	}

	public void setUf(Estado uf) {
		this.uf = uf;
	}

	public ClienteService getServiceCliente() {
		return serviceCliente;
	}

	public void setServiceCliente(ClienteService serviceCliente) {
		this.serviceCliente = serviceCliente;
	}

	public List<SelectItem> getNiveis() {
		return niveis;
	}

	public void setNiveis(List<SelectItem> niveis) {
		this.niveis = niveis;
	}

	public DataModel<Usuario> getUsuariosPesquisa() {
		return usuariosPesquisa;
	}

	public void setUsuariosPesquisa(DataModel<Usuario> usuariosPesquisa) {
		this.usuariosPesquisa = usuariosPesquisa;
	}

	public DataModel<ClienteUsuario> getUsuariosAdicionados() {
		return usuariosAdicionados;
	}

	public void setUsuariosAdicionados(DataModel<ClienteUsuario> usuariosAdicionados) {
		this.usuariosAdicionados = usuariosAdicionados;
	}

	public String getPesquisa() {
		return pesquisa;
	}

	public void setPesquisa(String pesquisa) {
		this.pesquisa = pesquisa;
	}
	
}
